Multiple Values

Version 3.0 of T supports multiple return values. This makes procedure call and return uniform, in the sense that a procedure can be invoked with zero or more values and can return zero or more values.


(return {value}*) $\Longrightarrow$ {value}* procedure

return returns its arguments as the value(s) of the current expression. In order to access the value(s) of a return expression the value(s) must be bound to identifiers using either receive or receive-values.

For example,

formula vobeyspaces :
!:}(lambda () (return 1 2 3)) $\Longrightarrow$ 1 2 3

where `` $\Longrightarrow$ 1 2 3'' denotes evaluates to the three values 1, 2, and 3.

Like procedures, continuations have certain expectations about the number of arguments (values) that will be delivered to them. It is an error if more or fewer values are delivered than expected. There are only a small number of ways to create continuations, thus one need only understand these cases:

  1. Implicit continuations, e.g. those receiving an argument of a combination or the predicate of an IF, expect exactly one value, thus

    formula vobeyspaces :
    !:} (list (values 1) 2) => (1 2)

    but

    formula vobeyspaces :
    !:} (list (values) 2) is an error (list (values 1 2) 2) is an error

  2. In a block (begin), a continuation which proceeds to execute subsequent commands (e.g. the continuation to the call to FOO in (BLOCK (FOO) 2)) accepts an arbitrary number of values, and discards all of them.

  3. receive expressions (and the subprimitive receive-values) creates a continuation which accepts whatever values are delivered to it, and passes them to a procedure; and of course it is an error if this procedure is passed the wrong number of values.

return when invoked invoked with no arguments returns to the calling procedure with no value. Thus (return) will return to its caller with no value. It is an error to return no value to a value-requiring position. For example,

formula vobeyspaces :
!:}(list 'a (return)) $\Longrightarrow$ error

The idiom (return) is useful for procedures that return an undefined value and many of the system procedures whose value(s) is undefined now return no value. However, the procedure undefined-value may provide a more informative error message.


(receive-values receiver sender) $\Longrightarrow$ value(s) of receiver procedure

receive-values returns the value of applying receiver, a procedure of n arguments, to the values returned by sender. sender is a thunk thunk , a procedure of no arguments, which returns n values.

For example,

formula vobeyspaces :
!:} (receive-values (lambda (x y) (list x y)) (lambda () (return 1 2))) $\Longrightarrow$ (1 2)


(receive ({ident}*) expression {body}*) $\Longrightarrow$ value of body syntax

In a receive form the expression is evaluated in the current environment and the values returned by the expression are bound to the corresponding identifiers. body, which should be a lambda body, i.e. a sequence of one or more expressions, is evaluated in the extended environment and the value(s) of the last expression in body is returned.

The expression

formula vobeyspaces :
!:} (receive (a b c) (return 1 2 3) (list a b c)) $\Longrightarrow$ (1 2 3)

is equivalent to

formula vobeyspaces :
!:} (receive-values (lambda (a b c) (list a b c)) (lambda () (return 1 2 3))) $\Longrightarrow$ (1 2 3)

Other forms have been extended in T3.0 to allow multiple return values:


(catch identifier {body}*) $\Longrightarrow$ value of body syntax

The identifier is bound to the continuation continuation of the catch form, which is now an n-ary procedure. This means that catch forms can ruturn multiple values. The continuation can be invoked only during the dynamic extent of the catch form (see section [*]). In T2 the continuation was a procedure of one argument. For example,

formula vobeyspaces :
!:}(catch x (list 1 (x 2 3) 4)) $\Longrightarrow$ 2 3


(ret {value}*) $\Longrightarrow$ {value}* procedure

Returns zero or more values as the value of the current read-eval-print loop.


$\textstyle \parbox{.75in}{\sc Note:}$ $\textstyle \parbox{\notewidth}{\em Multiple values are implemented efficiently. It may be more
efficient to use multiple values than to pass continuations.}$